package org.lib.redishello;

import java.time.Duration;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@SpringBootApplication
public class RedisHelloApplication {

	private static Consumer<Object> cs = System.out::println;
	
	public static void main(String[] args) {
		ConfigurableApplicationContext ctx = SpringApplication.run(RedisHelloApplication.class, args);
		
		// 调试用
//		studyContext(ctx);
	}
	
	public static void studyContext(ConfigurableApplicationContext ctx) {
		cs.accept("++++++studyContext++++++\nBeanDefinitionCount=" + ctx.getBeanDefinitionCount());
		String[] beanNames = ctx.getBeanDefinitionNames();
		cs.accept("beanNames.length=" + beanNames.length);
		cs.accept("输出Bean的名称：");
		Arrays.stream(beanNames).forEach((name)->{
			cs.accept("name=" + name);
		});
		
//		cs.accept("---");
//		Arrays.stream(beanNames).forEach((name)->{
//			cs.accept(String.format("name=%s, bean=%s", name, ctx.getBean(name).toString()));
//		});
		
		cs.accept("------studyContext------");
	}

}

/**
 * 测试 StringRedisTemplate 的使用
 * @author ben
 * @date 2021-08-23 11:52:03 CST
 */
//@Component
@Order(1)
@Slf4j
class TestRunner1 implements CommandLineRunner {

	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	
	@Override
	public void run(String... args) throws Exception {
		log.info("测试 StringRedisTemplate类：stringRedisTemplate={}", stringRedisTemplate);
		
		log.info("序列化器：{}\n{}\n{}\n{}", stringRedisTemplate.getKeySerializer(), stringRedisTemplate.getValueSerializer(),
				stringRedisTemplate.getHashKeySerializer(), stringRedisTemplate.getHashValueSerializer());
		
		stringRedisTemplate.opsForValue().set("test1", "str1");
		stringRedisTemplate.opsForValue().set("test2", "str2", Duration.ofSeconds(30));
		stringRedisTemplate.opsForValue().set("test3", "str3", 20);
		stringRedisTemplate.opsForValue().set("test4", "str4", 60, TimeUnit.SECONDS);
		
		String s1 = (String) stringRedisTemplate.opsForValue().get("test1");
		Long l1 = stringRedisTemplate.getExpire("test1");
		String s2 = (String) stringRedisTemplate.opsForValue().get("test2");
		Long l2 = stringRedisTemplate.getExpire("test2");
		String s3 = (String) stringRedisTemplate.opsForValue().get("test3");
		Long l3 = stringRedisTemplate.getExpire("test3");
		String s4 = (String) stringRedisTemplate.opsForValue().get("test4");
		Long l4 = stringRedisTemplate.getExpire("test4");
		
		log.info("执行结果：");
		log.info("s1={}, l1={}", s1, l1);
		log.info("s2={}, l2={}", s2, l2);
		log.info("s3={}, l3={}", s3, l3);
		log.info("s4={}, l4={}", s4, l4);
		
		log.info("del test1: {}", stringRedisTemplate.delete("test1"));
		log.info("del test2: {}", stringRedisTemplate.delete("test2"));
		log.info("del test3: {}", stringRedisTemplate.delete("test3"));
		log.info("del test4: {}", stringRedisTemplate.delete("test4"));
	}
	
}

/**
 * 测试 RedisTemplate 的使用
 * @author ben
 * @date 2021-08-23 13:18:54 CST
 */
//@Component
@Order(2)
@Slf4j
class TestRunner2 implements CommandLineRunner {

//	@Autowired // 添加泛型参数后，不可用，需改为 @Resource
	@Resource
	private RedisTemplate<String, Object> redisTemplate;
	
	@Override
	public void run(String... args) throws Exception {
		log.info("测试 RedisTemplate类：redisTemplate={}", redisTemplate);

		log.info("序列化器：{}\n{}\n{}\n{}", redisTemplate.getKeySerializer(), redisTemplate.getValueSerializer(),
				redisTemplate.getHashKeySerializer(), redisTemplate.getHashValueSerializer());
		
		redisTemplate.opsForValue().set("test1", "str1");
		redisTemplate.opsForValue().set("test2", "str2", Duration.ofSeconds(30));
		redisTemplate.opsForValue().set("test3", "str3", 20);
		redisTemplate.opsForValue().set("test4", "str4", 60, TimeUnit.SECONDS);
		
		String s1 = (String) redisTemplate.opsForValue().get("test1");
		Long l1 = redisTemplate.getExpire("test1");
		String s2 = (String) redisTemplate.opsForValue().get("test2");
		Long l2 = redisTemplate.getExpire("test2");
		
		// 异常发生！
		// 改造 RedisTemplate 的序列化器 后，可以执行了，见 {@link RedisConfig}
		String s3 = (String) redisTemplate.opsForValue().get("test3");
		Long l3 = redisTemplate.getExpire("test3");
		
		String s4 = (String) redisTemplate.opsForValue().get("test4");
		Long l4 = redisTemplate.getExpire("test4");
		
		log.info("执行结果：");
		log.info("s1={}, l1={}", s1, l1);
		log.info("s2={}, l2={}", s2, l2);
		log.info("s3={}, l3={}", s3, l3);
		log.info("s4={}, l4={}", s4, l4);
		
		log.info("del test1: {}", redisTemplate.delete("test1"));
		log.info("del test2: {}", redisTemplate.delete("test2"));
		log.info("del test3: {}", redisTemplate.delete("test3"));
		log.info("del test4: {}", redisTemplate.delete("test4"));
	}
	
}
